<template>
  <div class="practice-detail">
    <!-- 3D AI助手 -->
    <div 
      class="ai-assistant" 
      :class="{ 
        'is-speaking': isSpeaking,
        'is-dragging': isDragging 
      }" 
      :style="{ 
        left: position.x + 'px', 
        top: position.y + 'px',
        transform: isDragging ? 'scale(1.05)' : 'scale(1)'
      }"
    >
      <div class="assistant-container">
        <div 
          class="ai-model" 
          @mousedown.stop="startDrag"
          @click.stop="handleClick"
        >
          <a-tooltip 
            placement="right" 
            title="按住可拖拽移动"
            :mouseEnterDelay="0.3"
            :destroyTooltipOnHide="true"
          >
            <!-- 新的简约AI样式 -->
            <div class="ai-circle">
              <div class="ai-ring"></div>
              <div class="ai-core">
                <div class="ai-eye left"></div>
                <div class="ai-eye right"></div>
              </div>
            </div>
          </a-tooltip>
        </div>
        
        <!-- 对话框 -->
        <div class="holo-bubble" v-if="showBubble">
          <div class="bubble-content">
            <div class="holo-text">{{ currentMessage }}</div>
          </div>
          <div class="bubble-typing" v-if="isTyping">
            <span></span>
            <span></span>
            <span></span>
          </div>
        </div>
      </div>
    </div>

    <!-- 顶部导航栏 -->
    <div class="nav-header">
      <div class="left">
        <a-button class="back-btn" @click="$router.push('/practice')">
          <a-icon type="arrow-left" />
          返回题库
        </a-button>
      </div>
      <div class="right">
        <a-button 
          type="primary"
          class="collect-btn"
          :class="{ active: detail.isCollect === '0' }"
          :loading="collectLoading"
          @click="handleCollect"
        >
          <a-icon :type="detail.isCollect === '0' ? 'star' : 'star-o'" />
          {{ detail.isCollect === '0' ? '已收藏' : '收藏' }}
        </a-button>
      </div>
    </div>

    <!-- 主要内容区域 -->
    <div class="main-content">
      <!-- 题目信息 -->
      <div class="question-info">
        <div class="tags">
          <a-tag color="blue">{{ detail.subjectTypeName }}</a-tag>
          <a-tag :color="getLevelColor(detail.subjectLevel)">{{ detail.subjectLevelName }}</a-tag>
          <a-tag color="cyan">{{ detail.categoryName }}</a-tag>
        </div>
        <h1 class="title">{{ detail.subjectName }}</h1>
      </div>

      <!-- 答题区域 -->
      <div class="answer-section">
        <h2 class="section-title">
          {{ detail.subjectType === '2' ? '请选择正确答案：' : '请输入你的答案：' }}
        </h2>
        
        <!-- 选择题 -->
        <div v-if="detail.subjectType === '2'" class="choice-question">
          <div 
            v-for="option in detail.subjectOptions" 
            :key="option.option" 
            class="option-item"
            :class="{ selected: selectedOptions.includes(option.option) }"
            @click="toggleOption(option.option)"
          >
            <div class="option-marker">{{ option.option }}</div>
            <div class="option-content">{{ option.answer }}</div>
          </div>
        </div>

        <!-- 简答题 -->
        <div v-else class="text-question">
          <a-textarea
            v-model="textAnswer"
            :rows="8"
            placeholder="请在此输入你的答案..."
            :autoSize="{ minRows: 8, maxRows: 12 }"
            class="answer-textarea"
          />
        </div>
      </div>

      <!-- 底部导航区 -->
      <div class="bottom-nav">
        <div class="nav-wrapper">
          <a-button 
            class="nav-btn prev-btn"
            :disabled="!navigation.prevId"
            :loading="prevLoading"
            @click="handleNext(navigation.prevId)"
          >
            <a-icon type="left" />
            上一题
          </a-button>

          <a-button 
            type="primary" 
            class="submit-btn"
            :loading="submitLoading"
            @click="handleSubmit(true)"
          >
            交卷
          </a-button>

          <a-button 
            class="nav-btn next-btn"
            :disabled="!navigation.nextId && !$store.state.practice.hasMore"
            :loading="nextLoading"
            @click="handleNextNavigation"
          >
            下一题
            <a-icon type="right" />
          </a-button>
        </div>
      </div>
    </div>

    <!-- 结果模态框 -->
    <a-modal
      v-model="resultVisible"
      title="答题结果"
      :footer="null"
      width="600px"
      class="result-modal"
    >
      <div class="result-content">
        <div class="rate-section">
          <div class="rate-item">
            <a-progress
              type="circle"
              :percent="Number(animatedCorrectRate).toFixed(2)"
              :width="120"
              :strokeColor="{ '0%': '#108ee9', '100%': '#87d068' }"
            />
            <div class="rate-info">
              <span class="rate-label">正确率</span>
              <span class="rate-value">{{ Number(animatedCorrectRate).toFixed(2) }}%</span>
            </div>
          </div>
          <div class="rate-item">
            <a-progress
              type="circle"
              :percent="Number(animatedErrorRate).toFixed(2)"
              :width="120"
              status="exception"
            />
            <div class="rate-info">
              <span class="rate-label">错误率</span>
              <span class="rate-value">{{ Number(animatedErrorRate).toFixed(2) }}%</span>
            </div>
          </div>
        </div>
        <div class="count-info">
          <div class="count-item">
            <span class="count-label">总题数</span>
            <span class="count-value">{{ resultData.totalCount }}</span>
          </div>
          <div class="count-item">
            <span class="count-label">正确数</span>
            <span class="count-value correct">{{ resultData.correctCount }}</span>
          </div>
          <div class="count-item">
            <span class="count-label">错误数</span>
            <span class="count-value error">{{ resultData.errorCount }}</span>
          </div>
        </div>
        <div class="modal-footer">
          <a-button size="large" @click="resultVisible = false">返回</a-button>
          <a-button type="primary" size="large" @click="viewRecord">查看作答记录</a-button>
        </div>
      </div>
    </a-modal>

    <!-- 添加更多题目的模态框 -->
    <a-modal
      v-model="showNoMoreModal"
      title="提示"
      :footer="null"
      class="no-more-modal"
    >
      <div class="no-more-content">
        <a-icon type="info-circle" theme="filled" />
        <p>已经是最后一题了</p>
      </div>
    </a-modal>

    <!-- AI对话框 -->
    <a-modal
      v-model="aiChatVisible"
      title="智能问答"
      width="600px"
      :footer="null"
      :destroyOnClose="true"
      @cancel="handleModalClose"
    >
      <div class="ai-chat-container">
        <div v-if="isConnecting" class="connecting-status">
          <a-spin />
          <span>正在连接中...</span>
        </div>
        <template v-else>
          <div class="chat-messages" ref="chatMessages">
            <div v-for="(msg, index) in chatMessages" :key="index" class="message-item" :class="msg.type">
              <div class="message-content" :class="{ 'markdown-body': msg.type === 'ai' }">
                <div v-if="msg.type === 'ai'" v-html="parseMarkdown(msg.content)"></div>
                <template v-else>{{ msg.content }}</template>
              </div>
            </div>
          </div>
          <div class="chat-input">
            <a-input-search
              v-model="chatInput"
              placeholder="输入你的问题..."
              :loading="isReceiving"
              :disabled="isReceiving"
              enter-button="发送"
              @search="sendMessage"
            />
          </div>
        </template>
      </div>
    </a-modal>
  </div>
</template>

<script>
import { subject } from '@/api/subject'
import { marked } from 'marked'
import { mapGetters } from 'vuex'
import request from '@/utils/request'

export default {
  name: 'PracticeDetail',
  props: {
    id: {
      type: String,
      required: true
    }
  },
  data() {
    return {
      detail: {},
      loading: false,
      selectedOptions: [],
      textAnswer: '',
      resultVisible: false,
      resultData: {},
      showNoMoreModal: false,
      prevLoading: false,
      nextLoading: false,
      submitLoading: false,
      collectLoading: false,
      showBubble: false,
      currentMessage: '没有思路吗？点我为您解析目。',
      bubbleTimer: null,
      isSpeaking: false,
      isTyping: false,
      isHappy: false,
      animatedCorrectRate: 0,
      animatedErrorRate: 0,
      aiChatVisible: false,
      chatInput: '',
      chatLoading: false,
      chatMessages: [
        {
          type: 'ai',
          content: '你好！我是AI助手，有什么问题我可以帮你解答吗？'
        }
      ],
      position: {
        x: 30,
        y: window.innerHeight - 300
      },
      isDragging: false,
      dragOffset: {
        x: 0,
        y: 0
      },
      dragStartTime: 0,
      dragStartPos: { x: 0, y: 0 },
      ws: null,
      isConnecting: false,
      connectTimeout: null,
      isReceiving: false,
      messageTimer: null,
      lastMessageTime: 0
    }
  },
  computed: {
    ...mapGetters('practice', ['getNavigation']),
    navigation() {
      return this.getNavigation(this.$route.params.id)
    }
  },
  created() {
    this.fetchDetail()
  },
  methods: {
    async fetchDetail() {
      this.loading = true
      try {
        const res = await subject.getDetail(this.$route.params.id)
        this.detail = res.content
        // 重置答案
        this.selectedOptions = []
        this.textAnswer = ''
      } catch (error) {
        this.$message.error('获取题目详情失败')
      } finally {
        this.loading = false
      }
    },
    getLevelColor(level) {
      const colors = {
        '0': 'green',
        '1': 'cyan',
        '2': 'blue',
        '3': 'purple',
        '4': 'red'
      }
      return colors[level] || 'blue'
    },
    async handleCollect() {
      try {
        await subject.collect(this.id)
        this.$message.success('操作成功')
        this.fetchProblemDetail()
      } catch (error) {
        this.$message.error('操作失败')
      }
    },
    async handleNextNavigation() {
      if (!this.validateAnswer()) {
        this.$message.error('答案不能为空')
        return
      }

      if (!this.navigation.nextId && this.navigation.isLastItem) {
        if (this.$store.state.practice.hasMore) {
          this.nextLoading = true
          try {
            await this.$store.dispatch('practice/loadMoreIds')
            if (this.getNavigation(this.$route.params.id).nextId) {
              await this.submitAnswer(false)
              this.navigateToSubject(this.getNavigation(this.$route.params.id).nextId)
            } else {
              this.showNoMoreModal = true
            }
          } finally {
            this.nextLoading = false
          }
        } else {
          this.showNoMoreModal = true
        }
      } else {
        this.nextLoading = true
        try {
          await this.submitAnswer(false)
          this.navigateToSubject(this.navigation.nextId)
        } finally {
          this.nextLoading = false
        }
      }
    },
    validateAnswer() {
      if (this.detail.subjectType === '2') {
        return this.selectedOptions && this.selectedOptions.length > 0
      } else {
        return this.textAnswer && this.textAnswer.trim() !== ''
      }
    },
    async handleNext(id) {
      if (id) {
        this.prevLoading = true
        try {
          this.navigateToSubject(id)
        } finally {
          this.prevLoading = false
        }
      }
    },
    navigateToSubject(id) {
      this.$router.push(`/practice/${id}`)
    },
    async submitAnswer(showResult = false) {
      if (!this.validateAnswer()) {
        this.$message.error('答案不能为空')
        return false
      }

      this.submitLoading = true
      try {
        // 根据题目类型处理答案格式
        const subjectAnswer = this.detail.subjectType === '2' 
          ? JSON.stringify(this.selectedOptions) // 选择题：转为JSON字符串格式 ["A", "B", "D"]
          : this.textAnswer // 简答题：直接使用文本

        const res = await subject.submitAnswer({
          subjectId: this.detail.id,
          subjectAnswer,
          checkDone: showResult
        })

        if (showResult) {
          this.resultData = res.content
          this.resultVisible = true
        }

        return true
      } catch (error) {
        this.$message.error('提交答案失败')
        return false
      } finally {
        this.submitLoading = false
      }
    },
    // 提交答案
    async handleSubmit(showResult = false) {
      if (!this.validateAnswer()) {
        this.$message.error('答案不能为空')
        return false
      }

      this.submitLoading = true
      try {
        // 根据题目类型处理答案格式
        const subjectAnswer = this.detail.subjectType === '2' 
          ? JSON.stringify(this.selectedOptions) // 选择题：转为JSON字符串格式 ["A", "B", "D"]
          : this.textAnswer // 简答题：直接使用文本

        const res = await subject.submitAnswer({
          subjectId: this.detail.id,
          subjectAnswer,
          checkDone: showResult
        })

        if (showResult) {
          this.resultData = res.content
          this.resultVisible = true
        }

        return true
      } catch (error) {
        this.$message.error('提交答案失败')
        return false
      } finally {
        this.submitLoading = false
      }
    },
    // 点击下一题
    async handleNextQuestion() {
      // 提交当前答案，checkDone为false
      const subjectAnswer = this.detail.subjectType === '2' 
        ? JSON.stringify(this.selectedOptions)
        : this.textAnswer

      const res = await subject.submitAnswer({
        subjectId: this.detail.id,
        subjectAnswer,
        checkDone: false
      })
    },
    // 点击交卷
    async handleSubmitPaper() {
      // 提交当前答案，checkDone为true
      const subjectAnswer = this.detail.subjectType === '2' 
        ? JSON.stringify(this.selectedOptions)
        : this.textAnswer

      const res = await subject.submitAnswer({
        subjectId: this.detail.id,
        subjectAnswer,
        checkDone: true
      })
    },
    // 看作答记录
    viewRecord() {
      this.$router.push('/record')
    },
    getStatusIcon(status) {
      const icons = {
        completed: 'check-circle',
        wrong: 'close-circle',
        skipped: 'minus-circle',
        current: 'right-circle'
      }
      return icons[status] || 'question-circle'
    },
    refreshTip() {
      const index = this.tips.indexOf(this.currentTip)
      const nextIndex = (index + 1) % this.tips.length
      this.currentTip = this.tips[nextIndex]
    },
    formatTime(seconds) {
      const minutes = Math.floor(seconds / 60)
      const remainingSeconds = seconds % 60
      return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`
    },
    toggleNotebook() {
      this.notebookVisible = !this.notebookVisible
    },
    requestHint() {
      this.hintVisible = true
    },
    startTimer() {
      this.timer = setInterval(() => {
        this.spentTime++
      }, 1000)
    },
    stopTimer() {
      if (this.timer) {
        clearInterval(this.timer)
      }
    },
    showMessage(message, duration = 3000) {
      this.isTyping = true
      this.showBubble = true
      
      setTimeout(() => {
        this.isTyping = false
        this.currentMessage = message
        this.isSpeaking = true
        this.isHappy = true

        setTimeout(() => {
          this.showBubble = false
          this.isSpeaking = false
          this.isHappy = false
        }, duration)
      }, 1000)
    },

    randomMessage() {
      const messages = this.messages
      return messages[Math.floor(Math.random() * messages.length)]
    },

    randomEncouragement() {
      const encouragements = this.encouragements
      return encouragements[Math.floor(Math.random() * encouragements.length)]
    },

    handleAssistantClick() {
      this.handleAIChat()
    },
    async handleAIChat() {
      this.aiChatVisible = true;
      this.isConnecting = true;
      this.chatMessages = []; // 清空之前的消息
      
      // 设置连接超时
      this.connectTimeout = setTimeout(() => {
        if (this.isConnecting) {
          this.isConnecting = false;
          this.$message.error('连接超时，请重试');
        }
      }, 10000);
      
      try {
        await this.connectWebSocket();
        
        // 连接成功后发送当前题目
        if (this.ws && this.ws.readyState === WebSocket.OPEN) {
          // 添加欢迎消息
          this.chatMessages.push({
            type: 'ai',
            content: '你好！我是AI助手，让我来帮你分析这道题目。'
          });
          
          // 构造题目消息
          const questionMessage = `请帮我分析这道题目：${this.detail.subjectName}`;
          
          // 添加用户消息到聊天记录
          this.chatMessages.push({
            type: 'user',
            content: questionMessage
          });
          
          // 发送消息到服务器
          try {
            const res = await request({
              url: '/subject/qa/submit',
              method: 'post',
              data: { message: questionMessage }
            });
            console.log('发送题目成功:', res);
          } catch (error) {
            console.error('发送题目失败:', error);
            this.$message.error('发送题目失败，请重新发送');
            // 发送失败时移除用户消息
            this.chatMessages.pop();
          }
        }
      } catch (error) {
        console.error('WebSocket连接失败:', error);
        this.$message.error('连接失败，请重试');
        this.isConnecting = false;
      }
    },

    connectWebSocket() {
      return new Promise((resolve, reject) => {
        if (this.ws && this.ws.readyState === WebSocket.OPEN) {
          this.isConnecting = false;
          clearTimeout(this.connectTimeout);
          resolve();
          return;
        }

        // 假设用户ID为1，实际使用时应该从用户状态或配置中获取
        const userId = '1';
        this.ws = new WebSocket(`ws://localhost:4003/socket/subject/${userId}`);
        
        this.ws.onopen = () => {
          console.log('WebSocket连接成功');
          this.isConnecting = false;
          clearTimeout(this.connectTimeout);
          this.bindWebSocketEvents();
          resolve();
        };
        
        this.ws.onerror = (error) => {
          console.error('WebSocket错误:', error);
          this.isConnecting = false;
          clearTimeout(this.connectTimeout);
          reject(error);
        };

        this.ws.onclose = () => {
          console.log('WebSocket连接关闭');
          this.isConnecting = false;
          clearTimeout(this.connectTimeout);
        };
      });
    },

    bindWebSocketEvents() {
      if (!this.ws) return;
      
      this.ws.onmessage = (event) => {
        if (!event.data) return;
        
        this.lastMessageTime = Date.now();
        
        // 如果不是正在接收消息，创建新的AI消息
        if (!this.isReceiving) {
          this.isReceiving = true;
          this.chatMessages.push({
            type: 'ai',
            content: event.data
          });
        } else {
          // 如果正在接收消息，更新最后一条消息的内容
          this.chatMessages[this.chatMessages.length - 1].content = event.data;
        }
        
        // 清除之前的定时器
        if (this.messageTimer) {
          clearTimeout(this.messageTimer);
        }
        
        // 设置新的定时器，如果1秒内没有新消息，认为回答结束
        this.messageTimer = setTimeout(() => {
          if (Date.now() - this.lastMessageTime >= 1000) {
            this.isReceiving = false;
            this.messageTimer = null;
          }
        }, 1000);
        
        // 滚动到底部
        this.$nextTick(() => {
          const messagesContainer = this.$refs.chatMessages;
          if (messagesContainer) {
            messagesContainer.scrollTop = messagesContainer.scrollHeight;
          }
        });
      };
    },

    async sendMessage(value) {
      if (!value || !value.trim()) return;
      
      // 如果正在接收消息，不允许发送新消息
      if (this.isReceiving) {
        this.$message.warning('AI正在回答中，请稍候...');
        return;
      }

      // 如果WebSocket未连接，尝试重连接
      if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
        try {
          await this.connectWebSocket();
        } catch (error) {
          this.$message.error('连接已断开，请刷新页面重试');
          return;
        }
      }
      
      try {
        const message = value.trim();
        
        // 添加用户消息到聊天记录
        this.chatMessages.push({
          type: 'user',
          content: message
        });
        
        // 发送消息到服务器
        const res = await request({
          url: '/subject/qa/submit',
          method: 'post',
          data: { message }
        });
        console.log('发送消息成功:', res);
        
        // 重置输入框
        this.chatInput = '';
        
      } catch (error) {
        console.error('发送消息失败:', error);
        this.$message.error('发送消息失败，请重试');
        // 发送失败时移除之前添加的用户消息
        this.chatMessages.pop();
      }
    },

    startBubbleTimer() {
      if (this.bubbleTimer) {
        clearInterval(this.bubbleTimer)
      }
      
      this.bubbleTimer = setInterval(() => {
        this.showBubble = true
        this.isSpeaking = true
        setTimeout(() => {
          this.showBubble = false
          this.isSpeaking = false
        }, 2000)
      }, 4000)
    },
    toggleOption(option) {
      if (!this.selectedOptions) {
        this.selectedOptions = [];
      }
      const index = this.selectedOptions.indexOf(option);
      if (index > -1) {
        this.selectedOptions.splice(index, 1);
      } else {
        this.selectedOptions.push(option);
      }
    },
    startProgressAnimation() {
      const duration = 1500; // 动画持续1.5秒
      const startTime = Date.now();
      const correctTarget = (this.resultData.correctCount / this.resultData.totalCount) * 100;
      const errorTarget = (this.resultData.errorCount / this.resultData.totalCount) * 100;
      
      const animate = () => {
        const currentTime = Date.now();
        const elapsed = currentTime - startTime;
        const progress = Math.min(elapsed / duration, 1);
        
        // 使用缓动函数让动画更自然
        const easeProgress = 1 - Math.pow(1 - progress, 3);
        
        this.animatedCorrectRate = correctTarget * easeProgress;
        this.animatedErrorRate = errorTarget * easeProgress;
        
        if (progress < 1) {
          requestAnimationFrame(animate);
        }
      };
      
      requestAnimationFrame(animate);
    },
    startDrag(e) {
      // 记录开始拖拽的时间和位置
      this.dragStartTime = Date.now();
      this.dragStartPos = {
        x: e.clientX,
        y: e.clientY
      };
      
      this.isDragging = true;
      this.dragOffset = {
        x: e.clientX - this.position.x,
        y: e.clientY - this.position.y
      };
      
      document.addEventListener('mousemove', this.onDrag);
      document.addEventListener('mouseup', this.stopDrag);
      
      e.preventDefault();
      e.stopPropagation();
    },
    
    onDrag(e) {
      if (!this.isDragging) return;
      
      // 计算新位置
      let newX = e.clientX - this.dragOffset.x;
      let newY = e.clientY - this.dragOffset.y;
      
      // 限制在窗口范围内
      const maxX = window.innerWidth - 80;
      const maxY = window.innerHeight - 80;
      
      newX = Math.max(0, Math.min(newX, maxX));
      newY = Math.max(0, Math.min(newY, maxY));
      
      this.position = {
        x: newX,
        y: newY
      };
    },
    
    stopDrag() {
      document.removeEventListener('mousemove', this.onDrag);
      document.removeEventListener('mouseup', this.stopDrag);
      this.isDragging = false;
    },

    handleClick(e) {
      // 如果正在拖拽中，不触发点击
      if (this.isDragging) return;
      
      // 计算从按下到松开的时间和距离
      const dragEndTime = Date.now();
      const dragDuration = dragEndTime - this.dragStartTime;
      
      const dragDistance = Math.sqrt(
        Math.pow(e.clientX - this.dragStartPos.x, 2) +
        Math.pow(e.clientY - this.dragStartPos.y, 2)
      );
      
      // 如果移动距离小于5px且时间小于200ms则认为是点击
      if (dragDistance < 5 && dragDuration < 200) {
        this.handleAssistantClick();
      }
      
      e.preventDefault();
      e.stopPropagation();
    },
    
    // 窗口大小改变时调整位置
    handleResize() {
      const maxX = window.innerWidth - 80
      const maxY = window.innerHeight - 80
      
      this.position = {
        x: Math.min(this.position.x, maxX),
        y: Math.min(this.position.y, maxY)
      }
    },
    handleModalClose() {
      // 关闭WebSocket连接
      if (this.ws) {
        this.ws.close();
        this.ws = null;
      }
      
      // 清理定时器
      if (this.connectTimeout) {
        clearTimeout(this.connectTimeout);
      }
      if (this.messageTimer) {
        clearTimeout(this.messageTimer);
      }
      
      // 重置状态
      this.isConnecting = false;
      this.isReceiving = false;
      this.chatMessages = [
        {
          type: 'ai',
          content: '你好！我是AI助手，有什么问题我可以帮你解答吗？'
        }
      ];
    },
    // 添加markdown解析方法
    parseMarkdown(content) {
      if (!content) return '';
      try {
        return marked(content, {
          breaks: true,
          gfm: true,
          headerIds: false,
          mangle: false
        });
      } catch (error) {
        console.error('Markdown解析错误:', error);
        return content;
      }
    },
    // 添加新方法用于加载更多题目并导航
    async loadMoreAndNavigate() {
      try {
        await this.$store.dispatch('practice/loadMoreIds');
        const newNavigation = this.getNavigation(this.$route.params.id);
        if (newNavigation.nextId) {
          this.navigateToSubject(newNavigation.nextId);
        } else {
          this.showNoMoreModal = true;
        }
      } catch (error) {
        console.error('加载更多题目失败:', error);
        this.$message.error('加载更多题目失败');
      }
    },
  },
  mounted() {
    this.startTimer()
    this.startBubbleTimer()
    window.addEventListener('resize', this.handleResize)
  },
  beforeDestroy() {
    this.stopTimer()
    if (this.bubbleTimer) {
      clearInterval(this.bubbleTimer)
    }
    window.removeEventListener('resize', this.handleResize)
    // 清理拖拽事件监听器
    document.removeEventListener('mousemove', this.onDrag)
    document.removeEventListener('mouseup', this.stopDrag)
    if (this.ws) {
      this.ws.close();
      this.ws = null;
    }
    if (this.connectTimeout) {
      clearTimeout(this.connectTimeout);
    }
    if (this.messageTimer) {
      clearTimeout(this.messageTimer);
    }
  },
  // 监听路由参数化
  watch: {
    id: {
      handler() {
        this.fetchProblemDetail()
      }
    },
    resultVisible(newVal) {
      if (newVal) {
        // 当弹出显示时，开始动画
        this.animatedCorrectRate = 0;
        this.animatedErrorRate = 0;
        this.startProgressAnimation();
      } else {
        // 当弹窗关闭时，自动跳转到下一题
        if (this.navigation.nextId) {
          this.navigateToSubject(this.navigation.nextId);
        } else if (this.$store.state.practice.hasMore) {
          // 如果没有下一题但还有更多题目可加载
          this.loadMoreAndNavigate();
        }
      }
    }
  }
}
</script>

<style scoped>
.practice-detail {
  min-height: 100vh;
  background: #f8fafc;
}

/* 顶部导航栏 */
.nav-header {
  position: sticky;
  top: 0;
  left: 0;
  right: 0;
  height: 56px;
  background: white;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 24px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
  z-index: 100;
}

.back-btn {
  font-size: 14px;
}

.back-btn .anticon {
  margin-right: 8px;
}

/* 主要内容区域 */
.main-content {
  max-width: 800px;
  margin: 24px auto;
  padding: 0 24px;
}

/* 题目信息 */
.question-info {
  background: white;
  border-radius: 8px;
  padding: 20px;
  margin-bottom: 16px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}

.tags {
  margin-bottom: 12px;
}

.tags .ant-tag {
  margin-right: 8px;
  padding: 4px 12px;
  border-radius: 4px;
  font-size: 13px;
}

.title {
  font-size: 18px;
  color: #1f2937;
  margin: 0;
  line-height: 1.4;
}

/* 答题区域 */
.answer-section {
  background: white;
  border-radius: 8px;
  padding: 20px;
  margin-bottom: 80px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}

.section-title {
  font-size: 16px;
  color: #4b5563;
  margin: 0 0 20px;
  font-weight: 500;
}

/* 选择题样式 */
.choice-question {
  display: flex;
  flex-direction: column;
  gap: 12px;

  .option-item {
    display: flex;
    align-items: flex-start;
    padding: 12px 16px;
    margin-bottom: 12px;
    border: 1px solid #e8e8e8;
    border-radius: 4px;
    cursor: pointer;
    transition: all 0.3s;

    &:hover {
      border-color: #40a9ff;
      background: #f0f7ff;
    }

    &.selected {
      border-color: #1890ff;
      background: #e6f7ff;

      .option-marker {
        background: #1890ff;
        color: #fff;
      }
    }

    .option-marker {
      width: 24px;
      height: 24px;
      border-radius: 12px;
      background: #f5f5f5;
      color: #666;
      display: flex;
      align-items: center;
      justify-content: center;
      margin-right: 12px;
      font-weight: 500;
      transition: all 0.3s;
    }

    .option-content {
      flex: 1;
      font-size: 14px;
      line-height: 1.6;
      color: #333;
    }
  }
}

/* 简答题样式 */
.text-question {
  margin-top: 16px;
}

.answer-textarea {
  border-radius: 8px;
  padding: 16px;
  font-size: 15px;
  resize: none;
}

/* 底部导航 */
.bottom-nav {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  background: white;
  padding: 16px 24px;
  box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.05);
}

.nav-wrapper {
  max-width: 800px;
  margin: 0 auto;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
}

.nav-btn {
  min-width: 100px;
}

.submit-btn {
  min-width: 120px;
  height: 40px;
  font-size: 16px;
}

/* 结果模态框 */
.result-modal {
  .result-content {
    padding: 24px;
  }

  .rate-section {
    display: flex;
    justify-content: space-around;
    margin-bottom: 32px;
  }

  .rate-item {
    text-align: center;
  }

  .rate-info {
    margin-top: 16px;
  }

  .rate-label {
    font-size: 14px;
    color: #6b7280;
    display: block;
  }

  .rate-value {
    font-size: 24px;
    font-weight: 600;
    color: #1f2937;
    margin-top: 4px;
  }

  .count-info {
    display: flex;
    justify-content: space-around;
    margin-bottom: 32px;
    text-align: center;
  }

  .count-label {
    font-size: 14px;
    color: #6b7280;
  }

  .count-value {
    font-size: 24px;
    font-weight: 600;
    color: #1f2937;
    display: block;
    margin-top: 4px;
  }

  .count-value.correct {
    color: #10b981;
  }

  .count-value.error {
    color: #ef4444;
  }

  .modal-footer {
    text-align: center;
    gap: 16px;
    display: flex;
    justify-content: center;
  }
}

/* 无更题目态框 */
.no-more-modal {
  .no-more-content {
    text-align: center;
    padding: 24px;
  }

  .anticon {
    font-size: 48px;
    color: #1890ff;
    margin-bottom: 16px;
  }

  p {
    font-size: 16px;
    color: #4b5563;
    margin: 0;
  }
}

/* 响应式设计 */
@media (max-width: 768px) {
  .main-content {
    padding: 10px;
  }

  .question-info {
    padding: 12px;
    margin-bottom: 12px;
  }

  .title {
    font-size: 16px;
    line-height: 1.4;
    margin: 10px 0;
  }

  .answer-section {
    padding: 12px;
    margin-bottom: 60px;
  }

  .choice-question {
    .option-item {
      padding: 10px;
      margin-bottom: 8px;

      .option-marker {
        width: 20px;
        height: 20px;
        font-size: 12px;
        margin-right: 8px;
      }

      .option-content {
        font-size: 14px;
      }
    }
  }

  .text-question {
    margin-top: 12px;
  }

  .answer-textarea {
    padding: 12px;
    font-size: 14px;
  }

  .bottom-nav {
    padding: 12px;
  }

  .nav-wrapper {
    gap: 8px;
  }

  .nav-btn {
    min-width: 80px;
    font-size: 14px;
  }

  .submit-btn {
    min-width: 100px;
    height: 36px;
    font-size: 14px;
  }

  /* 结果模态框适配 */
  .result-modal {
    .result-content {
      padding: 16px;
    }

    .rate-section {
      flex-wrap: wrap;
      gap: 16px;
    }

    .rate-item {
      width: calc(50% - 8px);
    }

    .rate-value {
      font-size: 20px;
    }

    .count-info {
      flex-wrap: wrap;
      gap: 16px;
    }

    .count-value {
      font-size: 20px;
    }
  }
}

.collect-btn {
  min-width: 88px;
}

.collect-btn.active {
  background: #1890ff;
  border-color: #1890ff;
}

.collect-btn.active:hover {
  background: #40a9ff;
  border-color: #40a9ff;
}

.collect-btn .anticon {
  margin-right: 4px;
}

/* 新的简约AI助手样式 */
.ai-assistant {
  position: fixed;
  z-index: 1000;
  user-select: none;
  transition: transform 0.2s ease;
}

.ai-model {
  cursor: grab;
}

.ai-model:active {
  cursor: grabbing;
}

.ai-assistant.is-dragging {
  opacity: 0.8;
  z-index: 1001;
}

.ai-assistant.is-dragging .ai-model {
  cursor: grabbing;
}

.ai-circle {
  width: 56px;
  height: 56px;
  background: #ffffff;
  border-radius: 50%;
  position: relative;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.ai-ring {
  position: absolute;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  border: 2px solid transparent;
  border-top-color: #6366f1;
  animation: rotate 2s linear infinite;
}

.ai-core {
  width: 40px;
  height: 40px;
  background: linear-gradient(135deg, #6366f1, #8b5cf6);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: space-around;
  padding: 0 8px;
}

.ai-eye {
  width: 6px;
  height: 6px;
  background: #ffffff;
  border-radius: 50%;
  position: relative;
  animation: blink 4s infinite;
}

@keyframes rotate {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

@keyframes blink {
  0%, 45%, 55%, 100% { transform: scale(1); }
  50% { transform: scale(0.1); }
}

.holo-bubble {
  position: absolute;
  left: 80px;
  bottom: 10px;
  background: #ffffff;
  padding: 12px 16px;
  border-radius: 12px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
  min-width: 180px;
  max-width: 250px;
  border: 1px solid rgba(99, 102, 241, 0.1);
}

.holo-bubble::before {
  content: '';
  position: absolute;
  left: -6px;
  bottom: 20px;
  width: 12px;
  height: 12px;
  background: #ffffff;
  border-left: 1px solid rgba(99, 102, 241, 0.1);
  border-bottom: 1px solid rgba(99, 102, 241, 0.1);
  transform: rotate(45deg);
}

.bubble-content {
  color: #374151;
  font-size: 14px;
  line-height: 1.5;
}

.bubble-typing span {
  display: inline-block;
  width: 4px;
  height: 4px;
  background: #6366f1;
  border-radius: 50%;
  margin: 0 2px;
  animation: typing 1s infinite;
}

.bubble-typing span:nth-child(2) {
  animation-delay: 0.2s;
}

.bubble-typing span:nth-child(3) {
  animation-delay: 0.4s;
}

@keyframes typing {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-4px); }
}

.is-speaking .ai-core {
  animation: pulse 2s infinite;
}

@keyframes pulse {
  0% { transform: scale(1); }
  50% { transform: scale(1.05); }
  100% { transform: scale(1); }
}

/* AI聊天框样式 */
.ai-chat-container {
  display: flex;
  flex-direction: column;
  height: 600px;
  background: #f7f9fc;
}

.chat-messages {
  flex: 1;
  overflow-y: auto;
  padding: 24px;
  margin-bottom: 0;
  background: transparent;
}

.message-item {
  display: flex;
  margin-bottom: 20px;
  animation: fadeIn 0.3s ease;
}

.message-item.user {
  justify-content: flex-end;
}

.message-content {
  max-width: 85%;
  padding: 12px 16px;
  border-radius: 12px;
  font-size: 14px;
  line-height: 1.6;
  position: relative;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
}

.message-item.user .message-content {
  background: #f0f2f5;
  color: #1f2937;
  border-top-right-radius: 4px;
}

.message-item.ai .message-content {
  background: #ffffff;
  color: #1f2937;
  border-top-left-radius: 4px;
}

.chat-input {
  padding: 20px;
  background: #ffffff;
  border-top: 1px solid #edf2f7;
}

/* 修复输入框和发送按钮样式 */
:deep(.ant-input-search) {
  .ant-input-wrapper {
    border-radius: 24px;
    overflow: hidden;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
    
    .ant-input {
      height: 44px;
      padding: 0 20px;
      border: 1px solid #e5e7eb;
      border-right: none;
      font-size: 14px;
      
      &:focus {
        box-shadow: none;
      }
    }
    
    .ant-input-group-addon {
      background: transparent;
      padding: 0;
      border: none;
      
      .ant-input-search-button {
        height: 44px;
        width: 80px;
        border: 1px solid #1890ff;
        border-left: none;
        border-radius: 0 24px 24px 0 !important;
        font-size: 14px;
        box-shadow: none;
        
        &:hover {
          background: #40a9ff;
          border-color: #40a9ff;
        }
        
        &:active {
          background: #096dd9;
          border-color: #096dd9;
        }
      }
    }
  }
  
  &.ant-input-search-large .ant-input-search-button {
    height: 44px;
  }
}

/* 输入框禁用状态 */
:deep(.ant-input-disabled) {
  background: #f5f5f5;
  cursor: not-allowed;
  opacity: 0.8;
}

/* 发送按钮加载状态 */
:deep(.ant-input-search-button.ant-btn-loading) {
  opacity: 0.8;
  pointer-events: none;
}

.connecting-status {
  height: 400px;
  background: #ffffff;
}

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* 修改markdown样式 */
.markdown-body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  font-size: 14px;
  line-height: 1.6;
}

.markdown-body p {
  margin: 0 0 8px 0;
}

.markdown-body p:last-child {
  margin-bottom: 0;
}

.markdown-body pre {
  background: #f8fafc;
  border-radius: 8px;
  margin: 12px 0;
}

.markdown-body code {
  background: #f1f5f9;
  border-radius: 4px;
  font-size: 13px;
  padding: 2px 6px;
}

.markdown-body pre code {
  background: transparent;
  padding: 0;
}

.markdown-body blockquote {
  border-left: 4px solid #e5e7eb;
  color: #4b5563;
  margin: 12px 0;
  padding-left: 12px;
}

.markdown-body ul,
.markdown-body ol {
  margin: 8px 0;
  padding-left: 24px;
}

.markdown-body table {
  margin: 12px 0;
  border-radius: 8px;
  overflow: hidden;
}

.markdown-body th,
.markdown-body td {
  padding: 8px 12px;
  border: 1px solid #e5e7eb;
}

.markdown-body tr:nth-child(2n) {
  background: #f8fafc;
}

/* 滚动条样式 */
.chat-messages::-webkit-scrollbar {
  width: 4px;
}

.chat-messages::-webkit-scrollbar-track {
  background: transparent;
}

.chat-messages::-webkit-scrollbar-thumb {
  background: #cbd5e1;
  border-radius: 2px;
}

.chat-messages::-webkit-scrollbar-thumb:hover {
  background: #94a3b8;
}

/* 移动端适配 */
@media screen and (max-width: 768px) {
  :deep(.ant-modal) {
    margin: 0;
    padding: 0;
    max-width: 100%;
    top: 0;
    height: 100vh;
  }
  
  :deep(.ant-modal-content) {
    height: 100vh;
    border-radius: 0;
    display: flex;
    flex-direction: column;
  }
  
  :deep(.ant-modal-body) {
    flex: 1;
    padding: 0;
    height: calc(100vh - 55px);
    overflow: hidden;
  }
  
  .ai-chat-container {
    height: 100%;
  }
  
  .chat-messages {
    padding: 16px;
  }
  
  .message-content {
    max-width: 90%;
    font-size: 15px;
  }
  
  .chat-input {
    padding: 12px;
    background: #ffffff;
    border-top: 1px solid #edf2f7;
    position: sticky;
    bottom: 0;
  }
  
  :deep(.ant-input-search) {
    .ant-input-wrapper {
      .ant-input {
        height: 40px;
        font-size: 15px;
      }
      
      .ant-input-group-addon {
        .ant-input-search-button {
          height: 40px;
          width: 70px;
        }
      }
    }
  }
  
  /* 优化移动端滚动体验 */
  .chat-messages {
    -webkit-overflow-scrolling: touch;
  }
  
  /* 移动端点击态优化 */
  .message-content {
    -webkit-tap-highlight-color: transparent;
  }
  
  /* 移动端键盘弹出时的处理 */
  @supports (-webkit-touch-callout: none) {
    .ai-chat-container {
      height: -webkit-fill-available;
    }
  }
}

/* 平板适配 */
@media screen and (min-width: 769px) and (max-width: 1024px) {
  :deep(.ant-modal) {
    width: 90% !important;
  }
  
  .message-content {
    max-width: 88%;
  }
}
</style> 